package com.oa.system.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.joneying.common.web.response.Resp;
import com.oa.admin.entity.LeaveApply;
import com.oa.admin.service.ILeaveApplyService;
import com.oa.core.PageResult;
import com.oa.core.exception.DataIsEmptyException;
import com.oa.system.dto.ApprovalProcessAddDTO;
import com.oa.system.dto.MyApprovalListDTO;
import com.oa.system.entity.*;
import com.oa.system.mapper.ApprovalProcessDefineMapper;
import com.oa.system.service.*;
import com.oa.system.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class ApprovalProcessDefineServiceImpl extends ServiceImpl<ApprovalProcessDefineMapper, ApprovalProcessDefine> implements IApprovalProcessDefineService {

    @Autowired
    private ApprovalProcessDefineMapper approvalProcessDefineMapper;

    @Autowired
    private IApprovalPlanService approvalPlanService;

    @Autowired
    private IApprovalNodeService approvalNodeService;

    @Autowired
    private IApprovalNodeUserService approvalNodeUserService;

    @Autowired
    private IApprovalAfterHandleService approvalAfterHandleService;

    @Autowired
    private IApprovalAfterHandleUserService approvalAfterHandleUserService;

    @Autowired
    private IApprovalRuleService approvalRuleService;

    @Autowired
    private IUserService userService;

    @Override
    public PageResult<MyApprovalFindUserIdVO> myApprovalFindUserId(MyApprovalListDTO myApprovalListDTO) {
        Page page = myApprovalListDTO.getPage();
        return new PageResult<>(approvalProcessDefineMapper.myApprovalFindUserId(myApprovalListDTO, page), page);
    }

    @Override
    public PageResult<MyApprovalFindUserIdVO> findCopyRecord(MyApprovalListDTO myApprovalListDTO) {
        Page page = myApprovalListDTO.getPage();
        return new PageResult<>(approvalProcessDefineMapper.findCopyRecord(myApprovalListDTO, page), page);
    }

    @Override
    public PageResult<MyApprovalListVO> myApproval(MyApprovalListDTO myApprovalListDTO) {
        Page page = myApprovalListDTO.getPage();
        return new PageResult<>(approvalProcessDefineMapper.myApproval(myApprovalListDTO, page), page);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Resp add(ApprovalProcessAddDTO approvalProcessAddDTO) throws DataIsEmptyException {

        Date date = new Date();

        ApprovalProcessDefine approvalProcessDefine = new ApprovalProcessDefine();
        BeanUtils.copyProperties(approvalProcessAddDTO, approvalProcessDefine);

        deleteAll(approvalProcessDefine.getId());

        //修改流程
        if(insertOrUpdate(approvalProcessDefine)){

            if(approvalProcessAddDTO.getApprovalPlans() != null && approvalProcessAddDTO.getApprovalPlans().size() > 0){
                approvalProcessAddDTO.getApprovalPlans().forEach(d -> {
                    ApprovalPlan approvalPlan = new ApprovalPlan();
                    BeanUtils.copyProperties(d, approvalPlan);
                    approvalPlan.setCreateTime(date);
                    approvalPlan.setApprovalProcessId(approvalProcessDefine.getId());

                    //新增方案
                    if(approvalPlanService.insert(approvalPlan)){
                        List<ApprovalRule> approvalRules = new ArrayList<>();

                        if(d.getApprovalRules() != null && d.getApprovalRules().size() > 0){
                            d.getApprovalRules().forEach(r -> {
                                ApprovalRule approvalRule = new ApprovalRule();
                                BeanUtils.copyProperties(r, approvalRule);
                                approvalRule.setApprovalPlanId(approvalPlan.getId());
                                approvalRules.add(approvalRule);
                            });
                            //新增规则
                            approvalRuleService.insertBatch(approvalRules);
                        }

                        if(d.getApprovalNodes() != null && d.getApprovalNodes().size() > 0){
                            d.getApprovalNodes().forEach(e -> {
                                ApprovalNode approvalNode = new ApprovalNode();
                                BeanUtils.copyProperties(e, approvalNode);
                                approvalNode.setApprovalPlanId(approvalPlan.getId());

                                if(approvalNodeService.insert(approvalNode)){
                                    List<ApprovalNodeUser> approvalNodeUsers = new ArrayList<>();
                                    e.getApprovalNodeUsers().forEach(f -> {
                                        ApprovalNodeUser approvalNodeUser = new ApprovalNodeUser();
                                        BeanUtils.copyProperties(f, approvalNodeUser);
                                        approvalNodeUser.setApprovalNodeId(approvalNode.getId());
                                        approvalNodeUser.setUpdateTime(date);
                                        approvalNodeUsers.add(approvalNodeUser);
                                        //新增节点用户
                                        approvalNodeUserService.insertBatch(approvalNodeUsers);
                                    });
                                }
                            });
                        }else{
                            try {
                                throw new DataIsEmptyException("至少添加一个节点");
                            } catch (DataIsEmptyException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                });
            }else{
                throw new DataIsEmptyException("至少添加一个方案");
            }


            if(approvalProcessAddDTO.getApprovalAfterHandles() != null && approvalProcessAddDTO.getApprovalAfterHandles().size() > 0){
                approvalProcessAddDTO.getApprovalAfterHandles().forEach(d -> {
                    ApprovalAfterHandle approvalAfterHandle = new ApprovalAfterHandle();
                    BeanUtils.copyProperties(d, approvalAfterHandle);
                    approvalAfterHandle.setApprovalProcessId(approvalProcessDefine.getId());

                    if(approvalAfterHandleService.insert(approvalAfterHandle)){
                        List<ApprovalAfterHandleUser> approvalAfterHandleUsers = new ArrayList<>();
                        d.getApprovalAfterHandleUsers().forEach(e -> {
                            ApprovalAfterHandleUser approvalAfterHandleUser = new ApprovalAfterHandleUser();
                            BeanUtils.copyProperties(e, approvalAfterHandleUser);
                            approvalAfterHandleUser.setApprovalAfterHandleId(approvalAfterHandle.getId());
                            approvalAfterHandleUsers.add(approvalAfterHandleUser);

                            approvalAfterHandleUserService.insertBatch(approvalAfterHandleUsers);
                        });
                    }
                });
            }
            return new Resp().success();
        }
        return new Resp().failure();
    }

    private void deleteAll(String approvalProcessDefineId){
        approvalNodeUserService.delete(
                new EntityWrapper()
                        .where("approval_node_id in (select id from sys_approval_node where approval_plan_id in (select id from sys_approval_plan where approval_process_id = {0}))", approvalProcessDefineId)
        );

        approvalNodeService.delete(
                new EntityWrapper()
                        .where("approval_plan_id in (select id from sys_approval_plan where approval_process_id = {0})", approvalProcessDefineId)
        );

        approvalRuleService.delete(new EntityWrapper()
                .where("approval_plan_id in (select id from sys_approval_plan where approval_process_id = {0})", approvalProcessDefineId));

        approvalPlanService.delete(new EntityWrapper().eq("approval_process_id", approvalProcessDefineId));

        approvalAfterHandleUserService.delete(
                new EntityWrapper()
                        .where("approval_after_handle_id in (select id from sys_approval_after_handle where approval_process_id = {0})", approvalProcessDefineId)
        );

        approvalAfterHandleService.delete(new EntityWrapper().eq("approval_process_id", approvalProcessDefineId));


    }

    @Override
    public List<ApprovalProcessDefine> list() {
        return selectList(new EntityWrapper<>());
    }

    @Override
    public ApprovalProcessDefineDetails details(String id) {
        ApprovalProcessDefineDetails approvalProcessDefineDetails = approvalProcessDefineMapper.findDetailsById(id);

        if(approvalProcessDefineDetails != null){
            List<ApprovalAfterHandle> approvalAfterHandles =  approvalAfterHandleService.selectList(new EntityWrapper().eq("approval_process_id", approvalProcessDefineDetails.getId()));
            List<ApprovalAfterHandleListVO> approvalAfterHandleListVOS = new ArrayList<>();
            approvalAfterHandles.forEach(d -> {
                ApprovalAfterHandleListVO approvalAfterHandleListVO = new ApprovalAfterHandleListVO();
                BeanUtils.copyProperties(d, approvalAfterHandleListVO);
                approvalAfterHandleListVOS.add(approvalAfterHandleListVO);
            });

            approvalAfterHandleListVOS.forEach(d -> {
                List<ApprovalAfterHandleUserListVO> approvalAfterHandleUserListVOS = new ArrayList<>();
                List<ApprovalAfterHandleUser> approvalAfterHandleUsers = approvalAfterHandleUserService.selectList(new EntityWrapper().eq("approval_after_handle_id", d.getId()));

                approvalAfterHandleUsers.forEach(f -> {
                    User user = userService.selectById(f.getUserId());
                    ApprovalAfterHandleUserListVO approvalAfterHandleUserListVO = new ApprovalAfterHandleUserListVO();
                    approvalAfterHandleUserListVO.setUserId(user.getId());
                    approvalAfterHandleUserListVO.setName(user.getName());
                    approvalAfterHandleUserListVOS.add(approvalAfterHandleUserListVO);
                });
                d.setApprovalAfterHandleUsers(approvalAfterHandleUserListVOS);
            });
            approvalProcessDefineDetails.setApprovalAfterHandles(approvalAfterHandleListVOS);
        }

        return approvalProcessDefineDetails;
    }


}
